home *** CD-ROM | disk | FTP | other *** search
-
- /*
- File: TrueTypeLibrary.c
-
- Contains: graphics libraries - TrueType routines
-
- Written by: Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good, Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink, Chris Yerga
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <2> 1/9/95 JD changed 'boolean' to 'Boolean'
- <1> 1/9/95 JD First checked in.
- */
-
-
- #include <Memory.h>
- #include <GXFonts.h>
- #include <GXGraphics.h>
- #include <GXMath.h>
- #include "TrueTypeLibrary.h"
-
- #define AINT_WORD_ALIGN(n) ((n) & 1)
- #define WORD_ALIGN(n) (((n) + 1) & ~1L)
- #define AINT_LONG_ALIGN(n) ((n) & 3)
- #define LONG_ALIGN(n) (((n) + 3) & ~3L)
-
- #define IfDebug(condition, str) if (condition) DebugStr(str)
- #define CopyBytes(src, dst, count) BlockMove((Ptr)src, (Ptr)dst, count)
- #define TTDisposPtr(block) DisposePtr((Ptr)block)
-
-
- #define SFNT_MAGIC 0x5F0F3CF5
- #define SHORT_INDEX_TO_LOC_FORMAT 0
- #define LONG_INDEX_TO_LOC_FORMAT 1
- #define GLYPH_DATA_FORMAT 0
- #define FONT_HEADER_VERSION 0x10000
-
- typedef enum outlinePacking {
- ONCURVE = 1,
- XSHORT = 2,
- YSHORT = 4,
- REPEAT_FLAGS = 8,
- /* IF XSHORT */
- SHORT_X_IS_POS = 16, /* the short vector is positive */
- /* ELSE */
- NEXT_X_IS_ZERO = 16, /* the relative x coordinate is zero */
- /* ENDIF */
- /* IF YSHORT */
- SHORT_Y_IS_POS = 32, /* the short vector is positive */
- /* ELSE */
- NEXT_Y_IS_ZERO = 32 /* the relative y coordinate is zero */
- /* ENDIF */
- } outlinePacking;
-
- typedef enum componentPacking {
- COMPONENTCTRCOUNT = -1,
- ARG_1_AND_2_ARE_WORDS = 1, /* if not, they are bytes */
- ARGS_ARE_XY_VALUES = 2, /* if not, they are points */
- ROUND_XY_TO_GRID = 4,
- WE_HAVE_A_SCALE = 8, /* if not, Sx = Sy = 1.0 */
- NON_OVERLAPPING = 16,
- MORE_COMPONENTS = 32, /* if not, this is the last one */
- WE_HAVE_AN_X_AND_Y_SCALE = 64, /* Sx != Sy */
- WE_HAVE_A_TWO_BY_TWO = 128, /* t00, t01, t10, t11 */
- WE_HAVE_INSTRUCTIONS = 256, /* short count followed by instructions follows */
- USE_MY_METRICS = 512 /* use my metrics for parent glyph */
- } componentPacking;
-
- typedef struct {
- unsigned long bc;
- unsigned long ad;
- } BigDate;
-
- typedef struct {
- Fixed version; /* for this table, set to 1.0 */
- Fixed fontRevision; /* For Font Manufacturer */
- unsigned long checkSumAdjustment;
- unsigned long magicNumber; /* signature, should always be 0x5F0F3CF5 == MAGIC */
- unsigned short flags;
- unsigned short unitsPerEm; /* Specifies how many in Font Units we have per EM */
-
- BigDate created;
- BigDate modified;
-
- /** This is the gxFont wide bounding box in ideal space
- (baselines and metrics are NOT worked into these numbers) **/
-
- short xMin;
- short yMin;
- short xMax;
- short yMax;
-
- unsigned short macStyle; /* macintosh gxStyle word */
- unsigned short lowestRecPPEM; /* lowest recommended pixels per Em */
-
- /* 0: fully mixed directional glyphs, 1: only strongly L->R or T->B glyphs,
- -1: only strongly R->L or B->T glyphs, 2: like 1 but also contains neutrals,
- -2: like -1 but also contains neutrals */
-
- short fontDirectionHint;
-
- short indexToLocFormat;
- short glyphDataFormat;
- } sfntFontHeader;
-
-
- static Boolean EqualBytes(const void* a, const void* b, long byteCount)
- {
- register const char* ying = (const char *) a;
- register const char* yang = (const char *) b;
-
- while (byteCount--)
- if (*ying++ != *yang++)
- return false;
- return true;
- }
-
- static void* TTNewPtr(long size)
- {
- void* p = NewPtr(size);
-
- if (p == nil || MemError())
- Debugger();
- return p;
- }
-
- static Handle TTNewHandle(long size)
- {
- Handle block = NewHandle(size);
-
- if (block == nil || MemError())
- Debugger();
- return block;
- }
-
- static void* TTSetHandleSize(Handle block, long newSize)
- {
- SetHandleSize(block, newSize);
- if (MemError())
- Debugger();
- return *block;
- }
-
- static void* ResizeHandle(Handle block, long offset, long delta)
- {
- long size = GetHandleSize(block);
-
- if (delta > 0)
- { TTSetHandleSize(block, size + delta);
- BlockMove(*block + offset, *block + offset + delta, size - offset);
- }
- else
- { BlockMove(*block + offset - delta, *block + offset, size - offset + delta);
- TTSetHandleSize(block, size + delta);
- }
- return *block;
- }
-
- static Handle CopyFontTable(gxFont fontID, gxFontTableTag name)
- {
- long size, index;
-
- size = GXFindFontTable(fontID, name, nil, &index);
- if (size)
- { Handle table = TTNewHandle(size);
- HLock(table);
- GXGetFontTable(fontID, index, *table, nil);
- HUnlock(table);
- return table;
- }
- return nil;
- }
-
- static void* GetFontTablePtr(gxFont fontID, gxFontTableTag name)
- {
- long size, index;
-
- size = GXFindFontTable(fontID, name, nil, &index);
- if (size)
- { void* table = TTNewPtr(size);
- GXGetFontTable(fontID, index, table, nil);
- return table;
- }
- return nil;
- }
-
- #if 0
- long CountFontMetrics(gxFont fontID)
- {
- long count;
- Handle table;
-
- count = 0;
- if (table = CopyFontTable(fontID, fontMetricsTag))
- { count = ((fontMetricsHeader*)*table)->metricCount;
- DisposeHandle(table);
- }
- return count;
- }
-
- gxFontTableTag GetFontMetric(gxFont fontID, long index, long* pointIndex, long* glyphIndex)
- {
- Handle table;
- gxFontTableTag metricsTag = 0;
-
- if (table = CopyFontTable(fontID, fontMetricsTag))
- { fontMetricsHeader* fontMet = (fontMetricsHeader*)*table;
-
- if (glyphIndex)
- *glyphIndex = fontMet->glyphIndex + 1;
- if (index > 0 && index <= fontMet->metricCount)
- { fontWideMetric* metric = &fontMet->metric[index - 1];
- metricsTag = metric->name;
- if (pointIndex)
- *pointIndex = metric->pointIndex + 1;
- }
- DisposeHandle(table);
- }
- return metricsTag;
- }
-
- long FindFontMetric(gxFont fontID, gxFontTableTag metricsTag, long* pointIndex, long* glyphIndex)
- {
- Handle table;
- long index = 0;
-
- if (table = CopyFontTable(fontID, fontMetricsTag))
- { fontMetricsHeader* fontMet = (fontMetricsHeader*)*table;
- fontWideMetric* metric = fontMet->metric;
- fontWideMetric* stop = metric + fontMet->metricCount;
-
- if (glyphIndex)
- *glyphIndex = fontMet->glyphIndex + 1;
- while (metric < stop)
- { if (metric->name == metricsTag)
- { index = metric - fontMet->metric + 1;
- if (pointIndex)
- *pointIndex = metric->pointIndex + 1;
- break;
- }
- metric++;
- }
- DisposeHandle(table);
- }
- return index;
- }
-
- long SetFontMetric(gxFont fontID, long index, gxFontTableTag metricTag, long pointIndex, long glyphIndex)
- {
- Handle table;
-
- if (!index && !metricTag)
- { IfDebug(true, "\pmetricTag or index must non-zero");
- return 0;
- }
-
- if (table = CopyFontTable(fontID, fontMetricsTag))
- { fontMetricsHeader* fontMet = (fontMetricsHeader*)*table;
-
- if (glyphIndex)
- fontMet->glyphIndex = glyphIndex - 1;
- if (pointIndex == 0)
- goto DISPOSE_AND_EXIT;
- if (index < 0 || index > fontMet->metricCount)
- { IfDebug(true, "\pindex out of range");
- index = 0;
- goto DISPOSE_AND_EXIT;
- }
- if (index == 0)
- { long offset;
- fontWideMetric* metric, *stop;
-
- metric = fontMet->metric;
- stop = metric + fontMet->metricCount;
- while (metric < stop)
- { if (metric->name == metricTag)
- { metric->pointIndex = pointIndex - 1;
- index = metric - fontMet->metric + 1;
- goto DONE;
- }
- metric++;
- }
- /* MetricTag not found, append a new one.
- */
- offset = (char*)metric - (char*)fontMet->metric;
- fontMet = ResizeHandle(table, offset, sizeof(fontWideMetric));
- metric = (fontWideMetric*)((char*)fontMet->metric + offset);
- metric->name = metricTag;
- metric->pointIndex = pointIndex - 1;
- metric->flags = 0;
- index = ++fontMet->metricCount;
- }
- else
- { fontMet->metric[index - 1].name = metricTag;
- fontMet->metric[index - 1].pointIndex = pointIndex - 1;
- }
- DONE:
- HLock(table);
- GXSetFontTable(fontID, 0, fontMetricsTag, GetHandleSize(table), fontMet);
- DISPOSE_AND_EXIT:
- DisposeHandle(table);
- }
- else /* make a new table */
- { fontMetricsHeader* fontMet;
- long size = sizeof_fontMetricsHeader + sizeof(fontWideMetric);
-
- table = TTNewHandle(size);
- fontMet = (fontMetricsHeader*)*table;
- fontMet->version = 0x10000;
- fontMet->glyphIndex = glyphIndex - 1;
- fontMet->metricCount = index = 1;
- fontMet->metric[0].name = metricTag;
- fontMet->metric[0].pointIndex = pointIndex - 1;
- fontMet->metric[0].flags = 0;
- HLock(table);
- GXSetFontTable(fontID, 0, fontMetricsTag, size, fontMet);
- DisposeHandle(table);
- }
- EXIT:
- return index;
- }
-
- long DeleteFontMetric(gxFont fontID, long index, gxFontTableTag metricTag)
- {
- Handle table;
-
- if (!index && !metricTag)
- { IfDebug(true, "\pmetricTag or index must be non-zero");
- return 0;
- }
-
- if (table = CopyFontTable(fontID, fontMetricsTag))
- { fontMetricsHeader* fontMet = (fontMetricsHeader*)*table;
- fontWideMetric* stop, *metric;
-
- if (index > 0 && index <= fontMet->metricCount)
- { IfDebug(metricTag && fontMet->metric[index - 1].name != metricTag, "\pIndex and name are inconsistant");
- metric = fontMet->metric + index - 1;
- goto FOUND_IT;
- }
- else if (index != 0)
- { IfDebug(true, "\pDeleteFontMetric: index out of range");
- index = 0;
- goto DONE;
- }
- else
- { metric = fontMet->metric;
- stop = metric + fontMet->metricCount;
- while (metric < stop)
- { if (metric->name == metricTag)
- goto FOUND_IT;
- metric++;
- }
- }
- goto DONE;
- FOUND_IT:
- fontMet = ResizeHandle(table, (char*)metric - (char*)fontMet, - sizeof(fontWideMetric));
- index = --fontMet->metricCount;
-
- HLock(table);
- GXSetFontTable(fontID, 0, fontMetricsTag, GetHandleSize(table), fontMet);
- DONE:
- DisposeHandle(table);
- }
- EXIT:
- return index;
- }
- #endif
-
- /*
- * This guy only works with non-composits. This should be fixed.
- */
- long GetFontGlyphOutline(gxFont fontID, long glyphIndex, short* contourCount, short endPoint[], unsigned char onCurve[],
- short xCoord[], short yCoord[], short* instructionCount, unsigned char instructions[],
- glyphBoundingBox* bbox)
- {
- short* glyph, *glyphData;
- long size, contours, instrCount, points = 0;
-
- size = GetFontGlyphData(fontID, glyphIndex, nil);
- if (!size)
- { if (contourCount)
- *contourCount = 0;
- if (instructionCount)
- *instructionCount = 0;
- return 0;
- }
- glyphData = (short *) TTNewPtr(size);
- GetFontGlyphData(fontID, glyphIndex, glyphData);
-
- glyph = glyphData;
- contours = *glyph++;
- if (contourCount)
- *contourCount = contours;
- if (bbox)
- CopyBytes(glyph, bbox, 4 * sizeof(short));
-
- if (contours > 0)
- { glyph += 4; /* bounding box */
-
- if (endPoint)
- CopyBytes(glyph, endPoint, contours * sizeof(short));
-
- glyph += contours; /* end gxPoint [] */
- points = glyph[-1] + 1;
-
- instrCount = *glyph++;
- if (instructionCount)
- *instructionCount = instrCount;
- if (instructions)
- CopyBytes(glyph, instructions, instrCount);
- glyph = (short*)((char*)glyph + instrCount); /* glyph may now gxPoint to an odd byte, so don't use it as a (short*) */
-
- if (xCoord || yCoord || onCurve)
- { unsigned char* p, *byteP, *byteP2, flag, *flags;
- int z;
-
- p = (unsigned char*)glyph;
- flags = (unsigned char *) TTNewPtr(points);
-
- /* Do flags */
- byteP = flags;
- byteP2 = byteP + points;
- while (byteP < byteP2)
- { *byteP++ = flag = *p++;
- if ( flag & REPEAT_FLAGS )
- { int count = *p++;
- for (--count; count >= 0; --count)
- *byteP++ = flag;
- }
- }
-
- if (onCurve)
- { byteP = flags;
- byteP2 = byteP + points;
- while (byteP < byteP2)
- *onCurve++ = *byteP++ & ONCURVE;
- }
-
- /* Do X first */
- z = 0;
- byteP = flags;
- while (byteP < byteP2)
- { if ( (flag = *byteP++) & XSHORT )
- { if ( flag & SHORT_X_IS_POS )
- z += *p++;
- else
- z -= *p++;
- }
- else if ( !(flag & NEXT_X_IS_ZERO) ) /* This means we have a 2 byte vector */
- { z += (short)(*p++) << 8;
- z += *p++;
- }
- if (xCoord)
- *xCoord++ = z;
- }
-
- /* Now Do Y */
- if (yCoord)
- { z = 0;
- byteP = flags;
- while (byteP < byteP2)
- { if ( (flag = *byteP++) & YSHORT )
- { if ( flag & SHORT_Y_IS_POS )
- z += *p++;
- else
- z -= *p++;
- }
- else if ( !(flag & NEXT_Y_IS_ZERO) ) /* This means we have a 2 byte vector */
- { z += (short)(*p++) << 8;
- z += *p++;
- }
- *yCoord++ = z;
- }
- }
- TTDisposPtr(flags);
- }
- }
- TTDisposPtr(glyphData);
-
- return points;
- }
-
- void ComputeGlyphBBox(register glyphBoundingBox* bbox, const short xArray[], const short yArray[], int counter)
- {
- register int count = counter;
- register const short* oox = xArray;
- register const short* ooy = yArray;
-
- count--;
- bbox->xMin = bbox->xMax = *oox++;
- bbox->yMin = bbox->yMax = *ooy++;
-
- if (count > 0)
- do
- { register short coord = *oox++;
- if (bbox->xMin > coord)
- bbox->xMin = coord;
- else if (bbox->xMax < coord)
- bbox->xMax = coord;
-
- coord = *ooy++;
- if (bbox->yMin > coord)
- bbox->yMin = coord;
- else if (bbox->yMax < coord)
- bbox->yMax = coord;
- } while (--count);
- }
-
- /*
- * This guy only works with non-composits. This should be fixed.
- */
- void SetFontGlyphOutline(gxFont fontID, long glyphIndex, long contourCount, const short endPoint[], const unsigned char onCurve[],
- const short xCoord[], const short yCoord[], long instructionCount, const unsigned char instructions[],
- const glyphBoundingBox* bbox)
- {
- long size, points;
- void* data;
- short* sp;
-
- if (contourCount == 0)
- { size = 0;
- goto FINISH;
- }
-
- points = endPoint[contourCount - 1] + 1;
-
- /* Worst case size
- */
- size = sizeof(short) /* contours */
- + 4 * sizeof(short) /* bounds */
- + contourCount * sizeof(short) /* ep[] */
- + sizeof(short) /* instrCount */
- + instructionCount /* instr[] */
- + points * sizeof(char) /* flags[] */
- + points * sizeof(short) /* x[] */
- + points * sizeof(short); /* y[] */
-
- data = TTNewPtr(size);
-
- sp = (short*)data;
- *sp++ = contourCount;
- if (bbox)
- { CopyBytes(bbox, sp, 4 * sizeof(short));
- #ifdef debugging
- { glyphBoundingBox tempBBox;
- ComputeGlyphBBox(&tempBBox, xCoord, yCoord, points);
- if (!EqualBytes(&tempBBox, bbox, 4 * sizeof(short)))
- Debugger();
- }
- #endif
- }
- else
- ComputeGlyphBBox((glyphBoundingBox*)sp, xCoord, yCoord, points);
- sp += 4;
-
- CopyBytes(endPoint, sp, contourCount * sizeof(short));
- sp += contourCount;
-
- *sp++ = instructionCount;
- if (instructionCount)
- { CopyBytes(instructions, sp, instructionCount);
- sp = (short*)((char*)sp + instructionCount);
- }
-
- { unsigned char* flags, *flagsPtr;
- int i, x, y, count;
- char* bp;
- const short* xPtr = xCoord;
- const short* yPtr = yCoord;
-
- flagsPtr = (unsigned char *) TTNewPtr(points);
- flags = flagsPtr;
- x = y = 0;
- count = points;
- while (count--)
- { unsigned char flag = *onCurve++;
- int newy, newx = *xPtr++;
- int tmp = newx - x;
- if ( tmp == 0 )
- flag |= NEXT_X_IS_ZERO;
- else if ( tmp <= 255 && tmp >= -255 )
- { flag |= XSHORT;
- if (tmp > 0)
- flag |= SHORT_X_IS_POS;
- }
- newy = *yPtr++;
- tmp = newy - y;
- if ( tmp == 0 )
- flag |= NEXT_Y_IS_ZERO;
- else if ( tmp <= 255 && tmp >= -255 )
- { flag |= YSHORT;
- if (tmp > 0)
- flag |= SHORT_Y_IS_POS;
- }
- x = newx;
- y = newy;
- *flags++ = flag;
- }
-
- /* write out flags */
- bp = (char*)sp;
- for (i = 0; i < points; i++)
- { int k, count = 0;
-
- for ( k = i+1; k < points && flagsPtr[k] == flagsPtr[i] && count < 255; k++)
- count++;
- if ( count > 1 )
- { *bp++ = flagsPtr[i] | REPEAT_FLAGS;
- *bp++ = count;
- i += count;
- }
- else
- *bp++ = flagsPtr[i];
- }
-
- /* write out x coordinates */
- x = 0;
- count = points;
- flags = flagsPtr;
- while (count--)
- { int newx = *xCoord++;
- int tmp = newx - x;
- int flag = *flags++;
-
- if (flag & XSHORT)
- { if (!(flag & SHORT_X_IS_POS))
- tmp = -tmp;
- *bp++ = tmp;
- }
- else if (!(flag & NEXT_X_IS_ZERO))
- { *bp++ = tmp >> 8;
- *bp++ = tmp & 255;
- }
- x = newx;
- }
-
- /* write out y coordinates */
- y = 0;
- count = points;
- flags = flagsPtr;
- while (count--)
- { int newy = *yCoord++;
- int tmp = newy - y;
- int flag = *flags++;
-
- if (flag & YSHORT)
- { if (!(flag & SHORT_Y_IS_POS))
- tmp = -tmp;
- *bp++ = tmp;
- }
- else if (!(flag & NEXT_Y_IS_ZERO))
- { *bp++ = tmp >> 8;
- *bp++ = tmp & 255;
- }
- y = newy;
- }
-
- IfDebug(size < bp - (char*)data,(unsigned char *) "\pOverwrote buffer for packed data");
- size = bp - (char*)data; /* get the actual (smaller) size */
- TTDisposPtr(flagsPtr);
- }
- FINISH:
- SetFontGlyphData(fontID, glyphIndex, size, data);
- TTDisposPtr(data);
- }
-
- #define CountControlLongs(n) ((n) + 31 >> 5)
- #define NextPath(p) (gxPath*)((p)->controlBits + CountControlLongs((p)->vectors) + ((p)->vectors << 1))
- #define NextPoly(p) (gxPolygon*)((p)->vector + (p)->vectors)
-
- static unsigned char IsOnCurve(gxShapeType typeID, gxPaths* p, int indexBase0)
- {
- unsigned char onCurve = ONCURVE;
-
- if (typeID == gxPathType)
- { long* controlBits;
- gxPath* aPath = p->contour;
-
- while (indexBase0 >= aPath->vectors)
- { indexBase0 -= aPath->vectors;
- aPath = NextPath(aPath);
- }
- controlBits = aPath->controlBits + (indexBase0 >> 5);
- indexBase0 &= 31;
- onCurve = (*controlBits >> 31 - indexBase0) & 1 ? 0 : ONCURVE;
- }
- return onCurve;
- }
-
- static gxPoint* IndexedPoint(gxShapeType typeID, gxPaths* p, int indexBase0)
- {
- if (typeID == gxPathType)
- { gxPath* aPath = (gxPath*)p->contour;
-
- while (indexBase0 >= aPath->vectors)
- { indexBase0 -= aPath->vectors;
- aPath = NextPath(aPath);
- }
- return (gxPoint*)(aPath->controlBits + CountControlLongs(aPath->vectors)) + indexBase0;
- }
- else
- { gxPolygon* poly = (gxPolygon*)p->contour;
-
- while (indexBase0 >= poly->vectors)
- { indexBase0 -= poly->vectors;
- poly = NextPoly(poly);
- }
- return poly->vector + indexBase0;
- }
- }
-
- /*
- * Assumes the outline is at upem.16, so I can just call FixRound
- * on the coordinates and they will be in upem.
- *
- * Only works on gxPaths and gxPolygons.
- */
- void SetFontGlyphShape(gxFont fontID, long glyphIndex, gxShape s)
- {
- int contours, points, i;
- gxShapeType typeID;
- gxPaths* thePath;
- short* xCoord, *yCoord, *endPoint;
- unsigned char* onCurve;
- long attr;
-
- typeID = GXGetShapeType(s);
- contours = GXCountShapeContours(s);
- points = GXCountShapePoints(s, 0);
-
- endPoint = (short *) TTNewPtr((contours + 2 * points) * sizeof(short) + points);
- xCoord = endPoint + contours;
- yCoord = xCoord + points;
- onCurve = (unsigned char*)(yCoord + points);
-
- attr = GXGetShapeAttributes(s);
- GXSetShapeAttributes(s, attr | gxDirectShape);
- GXLockShape(s);
- thePath = (gxPaths *) GXGetShapeStructure(s, 0);
-
- { int ep = -1;
-
- for (i = 0; i < contours; i++)
- { ep += GXCountShapePoints(s, i + 1);
- endPoint[i] = ep;
- }
- }
- for (i = 0; i < points; i++)
- { gxPoint* pt = IndexedPoint(typeID, thePath, i);
- xCoord[i] = FixedRound(pt->x);
- yCoord[i] = - FixedRound(pt->y);
- onCurve[i] = IsOnCurve(typeID, thePath, i);
- }
-
- SetFontGlyphOutline(fontID, glyphIndex, contours, endPoint, onCurve, xCoord, yCoord, 0, nil, nil);
-
- GXUnlockShape(s);
- GXSetShapeAttributes(s, attr);
-
- TTDisposPtr(endPoint);
- }
-
- long GetFontGlyphData(gxFont fontID, long index, void* userCopy)
- {
- short format;
- long offset, length;
-
- { long count = GXCountFontGlyphs(fontID);
- if (index <= 0 || index > count) {
- GXPostGraphicsWarning(font_glyph_index_out_of_range);
- return -1;
- }
- index--;
- }
- { sfntFontHeader* head = (sfntFontHeader*) GetFontTablePtr(fontID, fontHeaderTag);
- format = head->indexToLocFormat;
- TTDisposPtr(head);
- }
- { void* location = GetFontTablePtr(fontID, indexToLocationTag);
- if (format == SHORT_INDEX_TO_LOC_FORMAT)
- { unsigned short* loc = (unsigned short*)location + index;
- offset = (long)loc[0] << 1;
- length = ((long)loc[1] << 1) - offset;
- }
- else
- { long* loc = (long*)location + index;
- offset = loc[0];
- length = loc[1] - offset;
- }
- TTDisposPtr(location);
- }
- if (userCopy && length)
- GXFindFontTableParts(fontID, glyphDataTag, offset, length, userCopy, nil);
- return length;
- }
-
- void SetFontGlyphData(gxFont fontID, long index, long newLength, void* data)
- {
- Handle table;
- long oldLength, offset, alignDelta, glyphs;
- short locFormat;
-
- glyphs = GXCountFontGlyphs(fontID);
- if (index <= 0 || index > glyphs)
- return;
- index--;
-
- { sfntFontHeader* head = (sfntFontHeader*) GetFontTablePtr(fontID, fontHeaderTag);
- locFormat = head->indexToLocFormat;
- TTDisposPtr(head);
- }
- table = CopyFontTable(fontID, indexToLocationTag);
- if (table)
- { if (locFormat == SHORT_INDEX_TO_LOC_FORMAT)
- { unsigned short* loc = (unsigned short*)*table + index;
- unsigned short* stop = (unsigned short*)*table + glyphs + 1;
-
- offset = (long)*loc++ << 1;
- oldLength = ((long)*loc << 1) - offset;
- alignDelta = (WORD_ALIGN(newLength) - oldLength) / 2;
- while (loc < stop)
- *loc++ += alignDelta;
- }
- else
- { long* loc = (long*)*table + index;
- long* stop = (long*)*table + glyphs + 1;
-
- offset = *loc++;
- oldLength = *loc - offset;
- alignDelta = WORD_ALIGN(newLength) - WORD_ALIGN(oldLength);
- while (loc < stop)
- *loc++ += alignDelta;
- }
-
- HLock(table);
- GXSetFontTable(fontID, 0, indexToLocationTag, GetHandleSize(table), *table);
- DisposeHandle(table);
- }
-
- GXSetFontTableParts(fontID, 0, glyphDataTag, offset, oldLength, WORD_ALIGN(newLength), data);
- if (AINT_WORD_ALIGN(newLength))
- { long zero = 0;
- GXSetFontTableParts(fontID, 0, glyphDataTag, offset + newLength, 1, 1, &zero);
- }
- }
-
-